# -*- coding: UTF-8 -*-

# FileName     : response
# Author       : EastsunW eastsunw@foxmail.com
# Create at    : 2022-04-22 18:19
# Last Modified: 2022-04-22 18:19
# Modified By  : EastsunW
# -------------
# Description  : 用于TF的自动补全，输入部分名字，返回匹配结果
# -------------

from flask_restful import Resource, reqparse


import uuid
import os
import pandas as pd
import time
import shutil
from threading import Timer


def perform_analysis(content, method):
    """根据传回来的变异内容（字符串）进行Motif预测
    Args:
        content (str): 变异内容，是一个原始字符串
    Returns:
        result: Json对象，直接用于数据返回
    Description:
        编写一个脚本，从传回的字符串开始，以获得Json格式的预测结果结束
        一些建议：将字符串写入文件，然后用本地脚本调用这个文件进行分析，
        等待将结果转换成JSON格式后，在此读取并返回。
    """
    mnvlist_tmp = content.split('\n')
    mnvlist = []
    chr_dict = {
        'chr1':    249250621,
        'chr10':   135534747,
        'chr11':   135006516,
        'chr12':   133851895,
        'chr13':   115169878,
        'chr14':   107349540,
        'chr15':   102531392,
        'chr16':   90354753,
        'chr17':   81195210,
        'chr18':   78077248,
        'chr19':   59128983,
        'chr2':   243199373,
        'chr20':   63025520,
        'chr21':   48129895,
        'chr22':   51304566,
        'chr3':   198022430,
        'chr4':   191154276,
        'chr5':   180915260,
        'chr6':   171115067,
        'chr7':   159138663,
        'chr8':   146364022,
        'chr9':   141213431,
        'chrX':   155270560,
    }
    base = ['a', 'g', 'c', 't', 'A', 'G', 'C', 'T']
    for i in mnvlist_tmp:
        a = i.split('_')
        if len(a) == 4:
            if a[0] in chr_dict.keys():
                pos = a[1].split(',')
                pos_len = len(pos)
                tag = 1
                for j in pos:
                    if not j.isdigit():
                        tag = 0
                if tag:
                    pos0 = [int(x) for x in pos]
                    if len(set(pos0)) == len(pos0) and max(pos0) - min(pos0) < 11 and min(pos0) > 30 and max(pos0) < chr_dict[a[0]]:
                        ref_list = a[2].split(',')
                        alt_list = a[3].split(',')
                        if len(ref_list) == pos_len and len(alt_list) == pos_len:
                            for y in range(pos_len):
                                if ref_list[y] not in base or alt_list[y] not in base or ref_list[y] == alt_list[y]:
                                    tag = 0
                            if tag:
                                pos1 = sorted(range(len(pos0)),
                                              key=lambda k: pos0[k])
                                pos_new = []
                                ref_new = []
                                alt_new = []
                                b = []
                                for m in pos1:
                                    pos_new.append(str(pos0[m]))
                                    ref_new.append(ref_list[m])
                                    alt_new.append(alt_list[m])
                                b.append(a[0])
                                a[1] = ','.join(pos_new)
                                b.append(a[1])
                                b.append('.')
                                a[2] = ','.join(ref_new)
                                a[3] = ','.join(alt_new)
                                b.append(a[2])
                                b.append(a[3])
                                b.append('.')
                                mnvlist.append('_'.join(b))
    # 写入随机命名文件
    uuid_str = uuid.uuid4().hex + str(time.time())
    tmp_dir = '/home/wangdy/MNVTFdb/Server/Services/Predict/tmp/' + uuid_str
    os.mkdir(tmp_dir)
    f = open(tmp_dir + '/' + uuid_str, 'w')
    for i in mnvlist:
        f.write(i + '\n')
    f.close()
    # 生成ref，alt序列
    getseq_cmd = '/home/caow/miniconda3/envs/mnvtfdb/bin/python /home/wangdy/MNVTFdb/Server/Services/Predict/scripts/generate_mnv_allelic_seqs.py -f /home/wangdy/MNVTFdb/Server/Services/Predict/resources/hg19.fa -s ' + \
        tmp_dir + '/' + uuid_str + ' -o ' + tmp_dir + '/' + \
        uuid_str + ' 2>' + tmp_dir + '/allelic_oligos.log'
    os.system(getseq_cmd)
    if method == 'deltaSVM':
        os.system('bash /home/wangdy/MNVTFdb/Server/Services/Predict/run_deltasvm.sh ' +
                  uuid_str + ' ' + uuid_str + '_out')
    elif method == 'fimo':
        os.system(
            'bash /home/wangdy/MNVTFdb/Server/Services/Predict/run_hocomoco.sh ' + uuid_str)
    outfile = tmp_dir + '/' + uuid_str + '_out'
    result = pd.read_table(outfile)
    t = Timer(21600, shutil.rmtree, (tmp_dir,))
    t.start()
    # shutil.rmtree(tmp_dir)
    r_dict = result.to_dict(orient='records')
    effect_count = result['Effect'].value_counts().to_dict()
    mnv_count = len(
        result.groupby(['Chr', 'Positions', 'Refs', 'Alts']).size()
        .to_dict()
    )
    tf_count = len(result['TF'].value_counts().to_dict())
    total_count = len(r_dict)
    result_dict = {}
    result_dict['mnv'] = mnv_count
    result_dict['tf'] = tf_count
    result_dict['gain'] = effect_count['Gain'] if 'Gain' in effect_count.keys() else 0
    result_dict['loss'] = effect_count['Loss'] if 'Loss' in effect_count.keys() else 0
    result_dict['total'] = total_count
    result_dict['details'] = r_dict
    return result_dict
    # json_out = 'out/' + uuid_str + '.json'
    # with open(json_out, 'w') as f:
    #     json.dump(result_dict, f, indent = 2)


class Predict_Class(Resource):

    def post(self):
        """返回表格数据的接口
        Arguments：
            content: str 输入的内容
        Returns:
            {
                mnv  : 0,
                tf   : 0,
                gain : 0,
                loss : 0,
                total: 0,
                details : Object[]
            }
        """
        # 获取参数：当前页码，每页结果数，查询类型和查询名称
        parser = reqparse.RequestParser()
        parser.add_argument(
            'content', type=str,
            required=True,
            nullable=True
        )
        parser.add_argument(
            'method', type=str,
            choices=["deltaSVM", "fimo"],
            required=True,
            nullable=True
        )
        request_args = parser.parse_args()
        assert request_args["content"]
        # 调用脚本来获取执行结果
        print(request_args)
        result = perform_analysis(
            request_args["content"],
            request_args["method"]
        )
        return result
